#include"header/abt.h"
#include"header/semantic.h"
#include"header/symbol.h"
#include<stdlib.h>
#include<stdio.h>

sym_table _now_scope_  = 0;

void semantic_error(char * msg){
    puts(msg);
    exit(0);
}

void init_semantic(){
    _now_scope_ = init_sym_table(NULL,SYMBOL_TABLE_DEFAULT_SIZE);
}

sym_table new_scope(){
    _now_scope_ = init_sym_table(_now_scope_,SYMBOL_TABLE_DEFAULT_SIZE);
    return _now_scope_;
}

sym_table append_scope(sym_table scope){
    scope->pre = _now_scope_;
    _now_scope_ = scope;
}

sym_table now_scope(){
    return _now_scope_;
}

sym_table exit_scope(){
    _now_scope_ = _now_scope_->pre;
    return _now_scope_;
}

void semantic_dec(abt_dec dec){
    sym_entry entry = NULL;
    sym_entry entry1 = NULL;
    sym_table table = NULL;
    char * ssym = NULL;
    abt_declist declist = NULL;
    entry = lookup_sym_entry(now_scope(),dec->sym,0);
    if(!entry){
        //如果名字在当前作用域已经用过,就汇报一个错误
        semantic_error("fatal error: name already used");
    }
    entry = NULL;
    if(dec->type == ABT_DEC_VOID){
        //空属性声明
        entry = init_void_entry(dec->sym);
        insert_sym_entry(now_scope(),entry);
    }else if(dec->type == ABT_DEC_INT){
        //整形申明
        entry = init_int_entry(dec->sym);
        insert_sym_entry(now_scope(),entry);
    }else if(dec->type == ABT_DEC_STRUCT){
        //结构体申明
        ssym = dec->info.struct_info.ssym;
        declist = dec->info.function_info.sdeclist;
        entry1 = lookup_sym_entry(now_scope(),ssym,0);
        if(entry1){
            //如果有这种类型的符号
            if(!declist){
                //有结构列表那就是重复声明
                semantic_error("fatal error: already declaration");
            }
            if(entry1->sym_info.type!=ABT_DEC_SPECIFIER){
                //不是选择器类型
                semantic_error("fatal error: name already used");
            }
            entry = init_struct_entry(dec->sym,ssym);
            insert_sym_entry(now_scope(),entry);
        }else{
            //如果还没有这种类型定义
            if(!ssym){
                semantic_error("fatal error: no specifier name");
            }
            if(!declist){
                semantic_error("fatal error: struct no declaration list");
            }
            //为结构创建私有符号表
            table = init_sym_table(NULL,SYMBOL_TABLE_DEFAULT_SIZE);
            append_scope(table);
            semantic_declist(declist);
            exit_scope();
            //结束符号表创建
            //创建选择器条目
            entry = init_specifier_entry(ssym,table);
            //插入选择器条目到当前作用域中
            insert_sym_entry(now_scope(),entry);

            //申明一个结构体实例
            entry = init_struct_entry(dec->sym,ssym);
            insert_sym_entry(now_scope(),entry);
        }
    }else if(dec->type == ABT_DEC_FUNCTION){
        entry = init_function_entry(dec->sym,dec->info.function_info.rtype);
        insert_sym_entry(now_scope(),entry);
    }else{
        semantic_error("fatal error: unkown declaration");
    }
}

typedef struct semantic_exp_info{
    int type;
    rtenv_access access;
}semantic_exp_info;

semantic_exp_info semantic_exp(abt_exp);

semantic_exp_info semantic_oper_exp(abt_exp exp){
    semantic_exp_info ret = {0,0};
    semantic_exp_info left_ret = {0,0};
    semantic_exp_info right_ret = {0,0};
    int op_type = exp->exp.oper_exp.op->type;

    left_ret = semantic_exp(exp->exp.oper_exp.left);
    right_ret = semantic_exp(exp->exp.oper_exp.right);

    switch(op_type){
        case ABT_OPER_EQUAL:
            ret.type = ABT_DEC_INT;
            ret.access = rtenv_eq(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_NOT_EQUAL:
            ret.type = ABT_DEC_INT;
            ret.access = rtenv_neq(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_GREAT:
            ret.type = ABT_DEC_INT;
            ret.access = rtenv_grt(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_GREAT_EQUAL:
            ret.type = ABT_DEC_INT;
            ret.access = rtenv_geq(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_LESS:
            ret.type = ABT_DEC_INT;
            ret.access = rtenv_les(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_LESS_EQUAL:
            ret.type = ABT_DEC_INT;
            ret.access = rtenv_leq(left_ret.access,right_ret.access);
            return ret;
        default:
            break;
    }
    
    if(left_ret.type != right_ret.type)
        semantic_error('fatal error: expression value type is different');
    
    if(left_ret.type == ABT_DEC_FUNCTION){
        semantic_error('fatal error: function value can not do arithmetic');
    }

    ret.type = left_ret.type;

    switch(op_type){
        case ABT_OPER_ADD:
            ret.access = rtenv_add(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_MINUS:
            ret.access = rtenv_sub(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_STAR:
            ret.access = rtenv_mul(left_ret.access,right_ret.access);
            return ret;
        case ABT_OPER_DIV:
            ret.access = rtenv_div(left_ret.access,right_ret.access);
            return ret;
        default:
            semantic_error("fatal error: unkown declaration");
    }
}

semantic_exp_info semantic_var_exp(abt_exp exp){
    sym_entry entry = 0;
    semantic_exp_info ret;
    entry = lookup_sym_entry(now_scope(),exp->exp.var_exp.var->sym,1);
    if(!entry){
        printf("fatal error: unkown variable: %s",exp->exp.var_exp.var->sym);
        semantic_error("");
    }
    switch(exp->exp.var_exp.var->type){
        case ABT_VAR_BASE:
            ret.type = entry->sym_info.type;
            return ret;
        case ABT_VAR_FIELD:
            if(entry->sym_info.type != ABT_DEC_STRUCT)
                emantic_error("fatal error: variable is not a Struct");
            return ret;
        case ABT_VAR_ARRAY:
            if(entry->sym_info.type != ABT_DEC_ARRAY)
                emantic_error("fatal error: variable is not a Array");
            return ret;
        default:
            semantic_error("fatal error: unkown declaration");
    }
}



void semantic_declist(abt_declist declist){
    abt_declist dlist = declist;
    abt_dec dec = 0;
    while(dlist){
        dec = dlist->dec;
        semantic_dec(dec);
        dlist = dlist->declist;
    }
}